grammar XPointer;

options {
	language=Java;
}
tokens {
	LBRACE='(';
	RBRACE=')';
	CIRC='^';
}

@header {
	package org.etourdot.xinclude.xpointer;
	
	import java.util.Map;
	import java.util.HashMap;
	import javax.xml.namespace.QName;
	import org.etourdot.xinclude.XIncProcConfiguration;
}
@lexer::header {
	package org.etourdot.xinclude.xpointer;
	
	import java.util.Map;
	import java.util.HashMap;
	import javax.xml.namespace.QName;
}
@members {
private XPointer xpointer = new XPointer();
private Map<String, String> namespaces = new HashMap<String, String>();
private XIncProcConfiguration configuration;

public void setConfiguration(final XIncProcConfiguration configuration) {
this.configuration = configuration;
}

public XPointer getXPointer() {
	return this.xpointer;
}
}

pointer:	(schemebased | shorthand) EOF
	;

shorthand
	:	NCNAME
		{
			xpointer.addPointerPart(configuration.getXPointerEngine().createPointerPart($NCNAME.text));
		}
	;

schemebased
	:	pointerpart (S? pointerpart)*
	;

pointerpart 
	:	schemename schemedata 
		{
			xpointer.addPointerPart(configuration.getXPointerEngine().createPointerPart($schemename.qname, $schemedata.data));
		}
	;

schemename returns[QName qname]
	:	prefixedname    { $qname = new QName("", $prefixedname.prefix, $prefixedname.lname); }
	      | unprefixedname  { $qname = new QName($unprefixedname.lname); }
	;

prefixedname returns[String prefix, String lname]
	:	p=NCNAME { $prefix = $p.text; } ':' l=NCNAME { $lname = $l.text; }
	;

unprefixedname returns[String lname]
	:	NCNAME { $lname = $NCNAME.text; }
	;

schemedata returns[String data]
	: 	LBRACE datacontent? RBRACE { $data = $datacontent.text; }
	;

datacontent
	:	ESCAPEDDATA | NCNAME
	;

NCNAME
	: 	NCNAMESTARTCHAR NCNAMECHAR*
	;

ESCAPEDDATA
	:	NORMALCHAR*
	;

fragment NORMALCHAR
	:	(CIRC_LBRACE | CIRC_RBRACE | DOUBLE_CIRC | ~(LBRACE | RBRACE | CIRC))
	;

fragment NCNAMESTARTCHAR
	: 	('A'..'Z' | '_' | 'a'..'z' | '\u00C0'..'\u00D6' | '\u00D8'..'\u00F6' | 
		 '\u00F8'..'\u02FF' | '\u0370'..'\u037D' | '\u037F'..'\u1FFF' | '\u200C'..'\u200D' | 
		 '\u2070'..'\u218F' | '\u2C00'..'\u2FEF' | '\u3001'..'\uD7FF' | '\uF900'..'\uFDCF' | 
		 '\uFDF0'..'\uFFFD')
	;

fragment NCNAMECHAR
	:   	(NCNAMESTARTCHAR | '-' | '.' | '0'..'9' | '\u00B7' | '\u0300'..'\u036F' | '\u203F'..'\u2040')
	;

fragment S	
	:	(' ' | '\t' | '\n' | '\r')+ { skip(); }
	;
	

fragment CIRC_LBRACE	:	'^(';
fragment CIRC_RBRACE	:	'^)';
fragment DOUBLE_CIRC	:	'^^';